/**
 * @Aurhor 把手给我
 * @Date 2022/9/6 20:01
 * @Version 1.0
 * websoket处理类，类似于servlet
 **/
package com.ft.websoket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ft.dao.UserDao;
import com.ft.domain.Message;
import com.ft.utils.MessageUtils;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@CrossOrigin
@Component
@ServerEndpoint("/chat/{userid}")
public class ChatEndpoint {
    //用来存储每个客服端对象对应发ChatEndpoint对象，可以通过id,或者用户名区分
    public static Map<String, ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();
    //声明Session对象，通过这个对象可以发送消息给指定用户
    private Session session;
    //用户id
    private String userId = "";
    @Autowired
    UserDao userdao;

    @OnOpen
    //建立链接时被调用
    public void OnOpen(Session session1, @PathParam("userid") String userid) {
        //将局部的session对象赋值给成员session
        this.session = session1;
        this.userId = userid;
        //连接建立成功后，将该对象存入容器中
        onlineUsers.put(userId, this);
        //将当前在线用户的用户名推送给所有客户端,或者vip功能
        //创建消息对象
        Message message = new Message();
        message.setSendUser(userId);
        message.setIsSystem(1);
        message.setMessage(userId+"上线了");
        brodcastAllUsers(message);
        Set<String> names = onlineUsers.keySet();
    }

    @OnMessage
    //接收到客户端发送的消息时被调用
    public void OnMessage(String message, Session session, @PathParam("userid") String userid) throws IOException {
        //将接收的信息转换成自己定义的message类对象
        //1.创建json对象,转换成message消息对象
        ObjectMapper obj = new ObjectMapper();
        Message message1 = obj.readValue(message, Message.class);
        //判断是否是心跳检查
        if(message1.getIsSystem() == 3 && message1.getMessage().equals("ping")){
            sendMessage(message1);
        }else {
            //发送消息给用户
            sendMessageByUser(message1);
        }
    }

    @OnClose
    //连接关闭时被调用
    public void OnClose(Session session, @PathParam("userid") String userid) {
        System.out.println(userId+"关闭了");
        onlineUsers.remove(userid);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误" + error);
        error.printStackTrace();
    }

    //推送消息给所有用户
    private void brodcastAllUsers(Message message) {
        synchronized (onlineUsers) {
            Set<String> names = onlineUsers.keySet();
            if (names.size() > 0) {
                for (String name : names) {
                    ChatEndpoint chatEndpoint = onlineUsers.get(name);
                    try {
                        ObjectMapper obj = new ObjectMapper();
                        chatEndpoint.session.getBasicRemote().sendText(obj.writeValueAsString(message));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 心跳检查服务端返回消息
     */
    public void sendMessage(Message message) throws IOException {
        ObjectMapper obj = new ObjectMapper();
        session.getBasicRemote().sendText(obj.writeValueAsString(message));
    }
    //私聊
    private void sendMessageByUser(Message message) throws IOException {
        Set<String> names = onlineUsers.keySet();
        boolean contains = names.contains(message.getReceiveUser());
        if (contains) {
            ObjectMapper obj = new ObjectMapper();
            ChatEndpoint chatEndpoint = onlineUsers.get(message.getReceiveUser());
            chatEndpoint.session.getBasicRemote().sendText(obj.writeValueAsString(message));
        } else {
            session.getBasicRemote().sendText("当前用户不在线");
        }
    }
}
